/* XBI */
/* xbiimage.h */

/*
  The XBIImage structure represents an Xbox disc image (also called an ISO file). The Xbox uses Dual-layer DVDs, and the Xbox disc structure takes this into account.
 
  A DVD stores its data in sectors, a sector being kXBIDVDSectorSize bytes long. The first sector is on at the center of the disc, on layer 0. Then the layer 0 expands up to the border of the actual DVD. The last sector of layer 0 is followed by the first sector of layer 1. The layer 1, on the opposite, starts on the edge of the disc, and spins back to the center. Therefore, the first sector of the first layer is actually just below the last sector of the last layer.
 
  There are several areas of interest in the Xbox disc structure :
 
 - A video partition : this is the video that plays when the DVD is inserted in any non-xbox, DVDVideo compliant device. (e.g. your computer). See xbiivh.h for more informations.
 - A game partition : this is where the actual game data reside. You'll notice this partition is invisible when you put an Xbox DVD in a computer.
 - A "security" partition : this is what the xbox' DVD drive deciphers to get access to the game partition. See xbiss.h for more informations
 
 Disc structure :
 
 
                      |   FILLER   |
 |-------------|------|------------|-------------------------------|----------| L1 <----
               VL1E   VL1S         GL1E                            GL1S
 
                      | FILLER |   |
 |--------|-----------|--------|PDS|-------------------------------|----------| L0 --->
          VL0S        VL0E         GL0S                            GLOE
     PSN  |0x30000
 
 VL0S = Video Layer0 Start
 VL0E = Video Layer0 End
 VL1S = Video Layer1 Start
 VL1E = Video Layer1 End
 GL0S = Game Layer0 Start
 GL0E = Game Layer0 End
 GL1S = Game Layer1 Start
 GL1E = Game Layer1 End
 PDS  = PFI, DMI, SS
 
 PSN = Physical Sector Number
 
 
 The conversion from PSN to LBA is quite easy for Xbox discs. The byte at LBA address 0 is actually PSN 0x30000. The arrangement of the PSN for Layer 1 (the second layer) is defined in the DVD spec as "The number calculated so that each bit of the End PSN (0) is inverted". What that means is to address a particular head position on Layer 1, you invert the BITs of the Layer 0 PSN address. Example LBA 0, which converted to PSN space is PSN address 0x30000. To find that same head position on Layer 1 you invert the bits of 0x30000. So that would be 0xFCFFFF.  (L1_PSN = L0_PSN xor 0xFFFFFF We use a 3 byte mask because the PSN values are defined as 3 byte fields, also remember the values from the PFI are in MSB byte order) That will give the PSN address to Layer 1 without moving the read head. That is important to understand in order to know what SplitVit is really doing on there OPT type double layer DVDs.
 */

 


#ifndef XBI_Image
#define XBI_Image 1

typedef struct _XBIImage XBIImage;

#include <xbi/xbiss.h>
#include <xbi/xbipfi.h>
#include <xbi/xbidmi.h>
#include <xbi/xbixfselement.h>
#include <xbi/xbixex.h>
#include <xbi/xbiivh.h>

// Creation - Copy - Deletion
XBIImage * XBIImageCreateFromFile(FILE * file, XBIError * error);
void XBIImageDelete(XBIImage * image);

// Data manipulation
int XBIImageIsXbox(XBIImage * image);
int XBIImageIsXbox360(XBIImage * image);
int XBIImageIsStealthPatched(XBIImage * image);
int XBIImageHasSplitVidPartition(XBIImage * image);
XBIXboxEXecutable * XBIImageGetDefaultXEX(XBIImage * image, XBIError * error);
size_t XBIImageCopyDataForXFSElement(XBIImage * image, byte_t * buffer, size_t bufferSize, XBIXFSElement * element, XBIError * error);
int XBIImageWriteXFSElementToFile(XBIImage * image, XBIXFSElement * element, FILE * file, XBIError * error);

// Accessors
FILE * XBIImageGetFilePointer(XBIImage * image);
off_t  XBIImageGetFileSize(XBIImage * image);
off_t  XBIImageGetFileSystemRootOffset(XBIImage * image);
off_t  XBIImageGetDataPartitionOffset(XBIImage * image);
XBIXFSElement * XBIImageGetRootFileSystemElement(XBIImage * image);
XBISecuritySector * XBIImageGetSS(XBIImage * image);
XBIPhysicalFormatInformation * XBIImageGetPFI(XBIImage * image);
XBIDiskManufacturingInformation * XBIImageGetDMI(XBIImage * image);
int XBIImageSetSS(XBIImage * image, XBISecuritySector * ss, XBIError * error);
int XBIImageSetPFI(XBIImage * image, XBIPhysicalFormatInformation * pfi, XBIError * error);
int XBIImageSetDMI(XBIImage * image, XBIDiskManufacturingInformation * dmi, XBIError * error);
XBIIntroVideoHalf * XBIImageGetFirstIVH(XBIImage * image);
XBIIntroVideoHalf * XBIImageGetSecondIVH(XBIImage * image);
int XBIImageSetFirstIVH(XBIImage * image, XBIIntroVideoHalf * video, XBIError * error);
int XBIImageSetSecondIVH(XBIImage * image, XBIIntroVideoHalf * video, XBIError * error);
#endif
